package com.qf.driver.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.qf.common.bean.R;
import com.qf.common.constant.CommonConstant;
import com.qf.common.dto.CmdParamDto;
import com.qf.common.dto.DeviceDto;
import com.qf.common.dto.DeviceTopicDto;
import com.qf.common.dto.ProductDto;
import com.qf.common.model.DeviceCmd;
import com.qf.common.model.QfDevice;
import com.qf.common.model.QfDeviceTopic;
import com.qf.common.model.QfProduct;
import com.qf.common.utils.JsonUtil;
import com.qf.driver.feign.DeviceFeign;
import com.qf.driver.feign.DeviceTopicFeign;
import com.qf.driver.feign.ProductFeign;
import com.qf.driver.mqtt.bean.MqttProperties;
import com.qf.driver.mqtt.handler.MqttSendCmdHandler;
import com.qf.driver.service.CmdService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * @author 千锋健哥
 */
@Slf4j
@Service
public class CmdServiceImpl implements CmdService {

    @Autowired
    private DeviceTopicFeign topicFeign;

    @Autowired
    private MqttSendCmdHandler mqttSendCmdHandler;

    @Autowired
    private MqttProperties mqttProperties;

    @Autowired
    private ProductFeign productFeign;

    @Autowired
    private DeviceFeign deviceFeign;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    public Boolean write(CmdParamDto dto) {
        //1. 根据设备key获取设备topic主题
        DeviceTopicDto topicDto = new DeviceTopicDto();
        topicDto.setDeviceKey(dto.getDeviceKey());
        R<List> topicResult = topicFeign.findAll(topicDto);
        if (topicResult.getData() == null || topicResult.getData().size() == 0) {
            return false;
        }

        //2. 组装指令, 将指令转换成json格式
        String command = JsonUtil.toJsonString(dto);

        //3. 从topic主题列表中, 获取该设备发送指令的topic
        String commandTopic = null;
        List<QfDeviceTopic> topicList = BeanUtil.copyToList(topicResult.getData(), QfDeviceTopic.class);
        for (QfDeviceTopic topic : topicList) {
            if (topic.getTopic().contains("/qfjava/device/ctrl")) {
                commandTopic = topic.getTopic();
            }
        }

        //4. 发送指令到emqx服务器
        try {
            mqttSendCmdHandler.sendToMqtt(commandTopic, mqttProperties.getQos(), command);
        } catch (Exception e) {
            mqttSendCmdHandler.sendToMqtt(commandTopic, command);
        }

        try {
            //5. 指定对象封装, 用于存储到mongodb中
            DeviceDto deviceDto = new DeviceDto();
            deviceDto.setDeviceKey(dto.getDeviceKey());
            R<List> deviceResult = deviceFeign.findAreaAll(deviceDto);
            QfDevice device = BeanUtil.toBean(deviceResult.getData().get(0), QfDevice.class);

            R<QfProduct> productResult = productFeign.selectById(String.valueOf(device.getProductId()));

            DeviceCmd deviceCmd = new DeviceCmd();
            //设备key
            deviceCmd.setDeviceKey(dto.getDeviceKey());
            //产品key
            deviceCmd.setProductKey(productResult.getData().getProductKey());
            //租户id
            deviceCmd.setTenantId(device.getTenantId());
            //继电器或者传感器编号
            deviceCmd.setDeviceSubCode(dto.getDeviceSubCode());
            //指令名称
            deviceCmd.setCmdName(dto.getCmdName());
            //指令值
            deviceCmd.setValue(dto.getValue());
            deviceCmd.setCreateTime(new Date());

            //6. 将指令对象发送到rabbitmq中,由数据中心center-data获取后存储到mongodb
            rabbitTemplate.convertAndSend(CommonConstant.Rabbit.TOPIC_EXCHANGE_VALUE,
                    CommonConstant.Rabbit.ROUTING_DEVICE_CMD_PREFIX + "command",
                    deviceCmd);
            return true;
        } catch (Exception e) {
            log.info("保存指令日志异常:" + dto);
            e.printStackTrace();
        }

        return false;
    }

}
